home *** CD-ROM | disk | FTP | other *** search
- {*********************************************************************
- * *** 三目並べ *** *
- * *
- * HAPPyのサンプルプログラム *
- * (作者 浅野比富美 Public Domain Software) *
- *********************************************************************}
-
- program TicTacToe(input,output) ; { 英語で tic-tac-toeという. }
- const o = 1 ; { 先手 ○ または 先手の勝ち.}
- n{othing} = 0 ; { 空き または 引き分け. }
- x = -o ; { 後手 × または 後手の勝ち.}
- type status = x..o ; { 盤の状態 または ゲーム評価値.}
- placeRange = 0..9 ; { 場所の範囲 (1~9がok). }
- tableType = array[placeRange] of status;{ ゲーム盤の型. }
- var table : tableType ; { ゲーム盤. }
- ox,you,com : status ; { ○または×. }
- time : integer ; { 1手目、2手目,3手目・・・ . }
-
- (****************************)
- (* 盤の表示処理 *)
- (****************************)
- procedure print ;
- var p : placeRange ;
- begin
- for p:=1 to 9 do
- begin case table[p] of
- o : write(' ○') ;
- n : write( p:3 ) ; { 置いていない場所は番号を表示.}
- x : write(' ×')
- end ;
- if p mod 3 = 0 then writeln { 3 つごとに改行する. }
- end ;
- writeln
- end {print} ;
-
- (****************************)
- (* 初期設定処理 *)
- (****************************)
- procedure init ;
- var p : placeRange ;
- ordinary : integer ;
- begin
- writeln('コンピュータと3目並べをしよう!') ;
- for p:=1 to 9 do table[p] := n ;
- write('先手○ 後手× を選んでネ(先手・・・1 後手・・・1以外) ? ') ;
- read(ordinary) ;
- if ordinary = 1 then you := o { 先手は ○ }
- else you := x ; { 後手は × . }
- com := -you ; { コンピュータはあなたの逆. }
- print { 置く場所を示すために盤を表示.}
- end {init} ;
-
- (****************************)
- (* 3つ並び判定関数 *) (*table に ox が 3つ並んでいれば真を返す *)
- (****************************) { table }
- function complete(table : tableType ; ox : status) : Boolean ; { 1 2 3 }
- var oooORxxx : -3..+3 ; { 4 5 6 }
- begin { 7 8 9 }
- oooORxxx := ox * 3 ;
- complete := (table[1]+table[2]+table[3] = oooORxxx) or { 1行目. }
- (table[4]+table[5]+table[6] = oooORxxx) or { 2行目. }
- (table[7]+table[8]+table[9] = oooORxxx) or { 3行目. }
- (table[1]+table[4]+table[7] = oooORxxx) or { 1列目. }
- (table[2]+table[5]+table[8] = oooORxxx) or { 2列目. }
- (table[3]+table[6]+table[9] = oooORxxx) or { 3列目. }
- (table[1]+table[5]+table[9] = oooORxxx) or { 右下がり.}
- (table[3]+table[5]+table[7] = oooORxxx) { 左下がり.}
- end {complete} ;
-
- (****************************)
- (* 最善の手を探す *)
- (****************************)
- (***** time手目のtableについて ox を 置ける 最善のplace を 調べる。
- 関数値:(ox・・勝ち n・・引き分け -ox・・負け) 負けの時 place は 無意味 *****)
- function bestSelect(table : tableType ; ox : status ; time : integer ;
- var place : placeRange) : status ;
- var p : placeRange ;
-
- (****************************)
- (* 思考ルーチン *)
- (****************************)
- function think : status ;
- label 9 ; { 関数出口. }
- var p,pp : placeRange ; { 置く場所 ppはダミー. }
- memoplace : placeRange ; { ワーク }
- eval : status ; { 評価値. }
- begin
- (* まずその局面で勝てる場所を探す *)
- for p := 1 to 9 do
- begin
- if table[p] = n then
- begin
- table[p] := ox ;
- if complete(table,ox) then { 3つ揃えば }
- begin
- place := p ;
- eval := ox ; { 勝ちが }
- goto 9 {return} { 決定. }
- end ;
- table[p] := n
- end
- end ;
- (* この局面だけでは勝てないので先読みする *)
- memoPlace := 0 ; { ループ後も0なら負け. }
- for p := 1 to 9 do
- begin
- if table[p] = n then
- begin
- table[p] := ox ; { そこに置いてみる. }
- eval := bestSelect(table,-ox,time+1,pp);{ 相手の最善手を調べる.}
- if eval = ox then
- begin
- place := p ;
- goto 9 {return}
- end
- else if eval = n then memoPlace :=p ; { 引き分けにできる場所.}
- table[p] := n { 置いたのを取り消す. }
- end
- end ;
- if memoPlace = 0 then eval := -ox { どこに置いても負け. }
- else eval := n ; { 引き分けにできる. }
- place := memoPlace ; { メモした場所を 返却. }
- 9: think := eval
- end {think} ;
-
- (****** bestSelect 開始 *****)
- begin {bestSelect} { 1 2 3 }
- case time of { 4 5 6 }
- 1 : begin { 7 8 9 }
- place := 5 ; { 1手目は真ん中 }
- bestSelect := n { 勝負は未決 }
- end ;
- 2 : begin
- p := 1 ;
- while table[p] = n do p := p + 1 ;
- if p=5 then place := 1 { 真ん中に置かれたのなら1 }
- else place := 5 ; { 真ん中以外なら真ん中を取る }
- bestSelect := n { 勝負は未決 }
- end ;
- 3,4,5,6,7,8 : bestSelect := think ; { 3~8手目は手を考える }
- 9 : begin { 9手目(最後の手)は 残った所 }
- place := 1 ;
- while table[place] <> n do place := place + 1 ;
- bestSelect := n { 勝負は引き分け }
- end
- end
- end {bestSelect} ;
-
- (****************************)
- (* あなたの手の処理 *)
- (****************************)
- procedure yourSelect ;
- var p : integer ;
- ok : Boolean ;
- pp : placeRange ;
- begin
- repeat
- if you = o then write('○')
- else write('×') ;
- write('をどこに置くかい (0:アドバイス 1~9:場所) ? ') ;
- read(p) ;
- if p = 0 then
- begin
- if bestSelect(table,you,time,pp) = com
- then writeln('既に君の負けは決定しているよ')
- else writeln(pp:2,'に置いたらどうかなあ') ;
- ok := false
- end
- else if (1<=p) and (p<=9) then ok := table[p] = n
- else ok := false
- until ok ; { 置ける場所が選ばれるまで.}
- table[p] := you { 選んだ場所に置く. }
- end {yourSelect} ;
-
- (****************************)
- (* コンピュータの番の処理 *)
- (****************************)
- procedure comSelect ;
- var place : placeRange ; { 置く場所. }
- d : status ; { 無意味だが処理上必要なもの.}
- begin
- write('コンピュータは') ;
- d := bestSelect(table,ox,time,place) ; { 最善の手を選び }
- writeln(place:2,' に置こう') ;
- table[place] := com { そこに 置く. }
- end {comSelect} ;
-
- (****************************)
- (* メイン処理 *)
- (****************************)
- begin {main}
- init ; { 初期設定をする. }
- ox := x ; { ○を先手とするテクニック. }
- time := 0 ; { 手数をクリアする. }
- repeat { 決着か8手目までやる. }
- time := time + 1 ; { 手数を進める. }
- ox := -ox ; { ○×を反転する. }
- if ox = you then yourSelect { あなたの番. }
- else comSelect ; { コンピュータの番 }
- print { 盤を表示する. }
- until complete(table,ox) or (time = 8{手目}) ; { 9手目はしない. }
- if complete(table,ox) then { 3つ揃った時 }
- if ox = you then writeln('コンピュータ故障!') { あなたは勝てない. }
- else writeln('コンピュータの勝ち') { コンピュータが揃った. }
- else writeln('引き分けだネ' ) { 8手目未決は引き分け. }
- end {main}.